﻿#include "qformfunction.h"
#include "ui_qformfunction.h"
#include<QTableWidgetItem>
#include<QMenu>
#include <QFileDialog>
#include <QDataStream>
#include <QToolBar>
#include <QVBoxLayout>
#include "globe.h"

//加入一行数据的方法
void QFormFunction::createItemsARow(int noNum, QString Direction, QString Time,
                                    QString Period, QString id, QString BitFormat,
                                    QString type, QString length, QString data)
{
    //为一行的单元格创建 Items
    QTableWidgetItem    *item;
//    QString str;
    //传送方向 一列
    //新建一个Item，设置单元格type为自定义的
    item=new  QTableWidgetItem(Direction,QFormFunction::ctDirection);
    item->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); //文本对齐格式
    item->setData(Qt::UserRole,QVariant(Direction));
    ui->tableinfo->setItem(noNum,QFormFunction::colDirection,item);

    //时间标识
    item = new QTableWidgetItem(Time,QFormFunction::ctTime);
    item->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); //文本对齐格式
    ui->tableinfo->setItem(noNum,QFormFunction::colTime,item);
    //报文周期
    item = new QTableWidgetItem(Period,QFormFunction::ctPeriod);
    item->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); //文本对齐格式
    ui->tableinfo->setItem(noNum,QFormFunction::colPeriod,item);
    //帧ID
    item = new QTableWidgetItem(id,QFormFunction::ctID);
    item->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); //文本对齐格式
    ui->tableinfo->setItem(noNum,QFormFunction::colID,item);
    //帧格式
    item = new QTableWidgetItem(BitFormat,QFormFunction::ctBitFormat);
    item->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); //文本对齐格式
    ui->tableinfo->setItem(noNum,QFormFunction::colBitFormat,item);
    //帧类型
    item = new QTableWidgetItem(type,QFormFunction::cttype);
    item->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); //文本对齐格式
    ui->tableinfo->setItem(noNum,QFormFunction::coltype,item);
    //数据长度
    item = new QTableWidgetItem(length,QFormFunction::ctlength);
    item->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); //文本对齐格式
    ui->tableinfo->setItem(noNum,QFormFunction::collength,item);

    //数据
    item = new QTableWidgetItem(data,QFormFunction::ctdata);
    item->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter); //文本对齐格式
    ui->tableinfo->setItem(noNum,QFormFunction::coldata,item);
}

void QFormFunction::setHeader()
{
    //设置表头
    QTableWidgetItem *headerItem;
    QStringList  headListText;
    headListText << "传输方向" << "时间标识" << "报文周期" << "帧ID"<<"帧格式"<<"帧类型"
                 <<"数据长度" << " \t\t\t数据\t\t\t";
    ui->tableinfo->setHorizontalHeaderLabels(headListText);  //添加表头
    ui->tableinfo->setColumnCount(headListText.count()); //设置有多少列  目前8列
    ui->tableinfo->horizontalHeader()->setStretchLastSection(true);
    //修改表头属性
    for(int i = 0;i<ui->tableinfo->columnCount();i++)
    {
        headerItem = new QTableWidgetItem(headListText.at(i));
        QFont font = headerItem->font();
        font.setBold(true); //设置粗体
        font.setPointSize(12);//字体大小
        headerItem->setTextColor(Qt::black);//加入颜色
        headerItem->setFont(font); //设置字体样式
        ui->tableinfo->setHorizontalHeaderItem(i,headerItem); //添加进取
    }
}
//获取数据
void QFormFunction::getMessage(int portNum, QString portName, int bps)
{
      this->m_portNum = portNum;
      this->m_portName = portName;
      this->m_bps = bps;
}

QFormFunction::QFormFunction(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::QFormFunction)
{
    ui->setupUi(this);
    setHeader();//设置表头

    ui->tableinfo->setContextMenuPolicy(Qt::CustomContextMenu); //在父窗口允许接收信号
    QToolBar* locToolBar = new QToolBar(tr("工具"),this); //创建工具栏
    locToolBar->addAction(ui->act_clear);
    locToolBar->addAction(ui->act_save);
    locToolBar->addAction(ui->act_message);
    locToolBar->addSeparator();
    locToolBar->addAction(ui->act_car_state);
    locToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    //页面布局部分
    QVBoxLayout *Layout = new QVBoxLayout();
    Layout->addWidget(locToolBar); //设置工具栏和编辑器上下布局
    Layout->addWidget(ui->groupBox);
    Layout->addWidget(ui->groupBox_2);
    Layout->setContentsMargins(2,2,2,2); //减小边框的宽度
    Layout->setSpacing(2);
    this->setLayout(Layout); //设置布局
    bridge = new QBridge();
    pCarStatus = new QCarStatusForm(this); //
    //连接两个数据的信号，通过CAN口的数据来完成的
    connect(&(bridge->threadCar),SIGNAL(message_signal(QString,QString,QString,QString,QString,QString,QString,QString)),
            this,SLOT(onThreadCar_Message(QString,QString,QString,QString,QString,QString,QString,QString)));

//    connect(&threadCar,SIGNAL(message_Array(uint ID ,BYTE const[])),this,SLOT(onTreadCar_CAN_Array(uint ID,BYTE const[])));

    connect(&(bridge->threadCar),SIGNAL(message_Array(uint , uchar *)),this,SLOT(onTreadCar_CAN_Array(uint ,uchar *)));
}

QFormFunction::~QFormFunction()
{
    delete ui;
}
//发送过来的消息
void QFormFunction::onThreadCar_Message(QString ID, QString TimeStamp, QString TimeFlag,
                                        QString SendType, QString RemoteFlag,
                                        QString ExternFlag, QString DataLen,
                                        QString Data)
{
     Q_UNUSED(SendType)
     int curRow = ui->tableinfo->rowCount();
     ui->tableinfo->insertRow(curRow);
     createItemsARow(curRow,"accept",TimeStamp,TimeFlag,
                     ID,ExternFlag,RemoteFlag,DataLen,Data);
}

void QFormFunction::onTreadCar_CAN_Array(uint ID,uchar * Array)
{
    if( 0x01A1 == ID )//控制报文
    {
       //byte1
       part1.mode = Array[0]>>5 & 0x03; //工作模式选择
       part1.state = Array[0]>>3 & 0x03; //工作状态选择

       //byte2
       part1.light = Array[1] & 0x01;
       part1.standby1 =  (Array[1]>>1) & 0x01;
       part1.standby2 =  (Array[1]>>2) & 0x01;
       part1.right_enable = (Array[1]>>3) & 0x01;
       part1.left_enable = (Array[1]>>4) & 0x01;
       part1.back_enable = (Array[1]>>5) & 0x01;
       part1.forword_enable = (Array[1]>>6) & 0x01;
       part1.stop_car = (Array[1]>>7) & 0x01;
       //byte3  keep

       //byte5 byte4
       part1.speed = ((int)(Array[4] << 8) + Array[3]) * 0.1;
       //byte7 byte6
       part1.angle = ((int)(Array[6] << 8) + Array[5]) * 0.1;
       //解析后加载到界面
       pCarStatus->controlCarMessage1(part1.mode,part1.state,part1.speed, part1.angle);
       pCarStatus->carStatus(part1.light,part1.standby1,part1.standby2,
                            part1.right_enable, part1.left_enable,part1.back_enable,
                            part1.forword_enable,part1.stop_car);

    }
    else if(0x01B1 == ID)  //状态报文1
    {
       //byte1
       part2.state = Array[0]>>7 & 0x01; //工作状态
       part2.mode = (Array[0] >>5) & 0x03; //工作模式选择
       part2.control = (Array[0] >>3) & 0x03; //控制方式
       part2.await = (Array[0] >>1) & 0x03; //是否立即进入待机状态
       part2.error = Array[0] & 0x01; //错误状态

       //byte2
       part2.power = Array[1]; //电量
       //byte3
       part2.error_level = Array[2]>>6 & 0x03; //故障等级
       part2.BMS_state =  Array[2]>>4 & 0x03;  //BMS
       part2.high_volt =  Array[2] >> 3 &0x01; //高压连接状态
       part2.charge_status =  Array[2] >> 2 &0x01; //继电器状态
       part2.tem_sys =  Array[2] & 0x03; //温度系统状态

       // byte4  byte5
       part2.bat_v = (int(Array[4] << 8) + Array[3]) * 0.1;

       // byte6  byte7
       part2.bat_i = (int(Array[6] << 8) + Array[5]) * 0.1 -1000;

       //解析后加载到界面
       pCarStatus->AllCarStatus(part2.state,part2.mode,part2.control,
                                part2.await,part2.error,part2.power);

       pCarStatus->AllCarStatus2(part2.error_level,part2.BMS_state,part2.high_volt,
                                part2.charge_status, part2.tem_sys,
                                part2.bat_v, part2.bat_i);

    }
    else if(0x01B2 == ID)  //状态报文2
    {
       part3.turn_angle_1 = (int( Array[1]<<8) + Array[0]) *0.1;
       part3.turn_angle_2 = (int( Array[3]<<8) + Array[2]) *0.1;
       bool ok;
       ok = Array[5]>>7;
       part3.turn_vel_1 = (int((Array[5] &0x3f) <<8)+ Array[4]) * 0.1;
       if(!ok)
       {
          part3.turn_vel_1 = -part3.turn_vel_1;
       }
       ok = Array[7]>>7;
       part3.turn_vel_2 = (int((Array[7] &0x3f) <<8)+ Array[6]) * 0.1;
       if(!ok)
       {
          part3.turn_vel_2 = -part3.turn_vel_2;
       }
       //加载到界面上
       pCarStatus->AllCarPart3(part3.turn_angle_1,part3.turn_angle_2,
                               part3.turn_vel_1,part3.turn_vel_2);

    }

    else if(0x01B3 == ID)
    {
        //
        int ok = Array[1] >>7;
        part4.speed = ((int(Array[1] &0x3f) << 8) +  Array[0]) * 0.1;
        if(!ok)
        {
           part4.speed = - part4.speed;
        }

        part4.angle =  (int(Array[3] << 8)+ Array[2]) * 0.1;

        pCarStatus->AllCarPart4(part4.speed,part4.angle);
    }
}
void QFormFunction::on_btn_Aut_send_clicked()
{

}
//发送数据
void QFormFunction::on_btn_send_clicked()
{
     bridge->threadCar.startthread();
     bridge->threadCar.start(); //开启线程
}
//停止接收
void QFormFunction::on_btn_stop_clicked()
{
     bridge->threadCar.stop();
     bridge->threadCar.wait();
  //  unsigned int id,unsigned char *ch
    //yuphe
//    unsigned char ch[8]={0,0,0,0,0,0,0,0};
//    bridge->threadCar.TransmitCANThread(0x1a1,ch);
}

void QFormFunction::on_act_clear_triggered()
{
    ui->tableinfo->clearContents(); //清空所有数据 不清空表头

}

void QFormFunction::on_tableinfo_customContextMenuRequested(const QPoint &pos)
{
    Q_UNUSED(pos)
    QMenu *menuList = new QMenu(this);
    //添加菜单项
    menuList->addAction(ui->act_clear);
    menuList->addAction(ui->act_save);
    menuList->addAction(ui->act_message);
    menuList->addSeparator();
    menuList->addAction(ui->act_car_state);
    menuList->exec(QCursor::pos()); //在当前光标下显示
    delete menuList;
}

void QFormFunction::on_act_save_triggered()
{
    //添加保存数据方案，
    QString curPath = QDir::currentPath();
    QString dlgTitle=tr("另存为一个文件");
    QString filter = "逗号分隔符文件(*.csv)";
    QString aFileName = QFileDialog::getSaveFileName(this,dlgTitle,curPath,filter);
    if (aFileName.isEmpty())
        return; //
}

void QFormFunction::on_act_message_triggered()
{
    //显示报文筛选的界面
    QDialogMessage * message = new QDialogMessage(this);
    Qt::WindowFlags flogs = message->windowFlags();
    message->setWindowFlags(flogs|Qt::MSWindowsFixedSizeDialogHint);//设置对话框固定大小
    int ret = message->exec();
    if(ret == QDialog::Accepted)
    {
        //点击确定会执行
    }
    else {
        //点击取消会执行
    }

}

void QFormFunction::on_act_car_state_triggered()
{
    //显示行车状态界面，采用一个界面，不出现两次界面
    pCarStatus->setWindowTitle(m_portName);
    pCarStatus->setWindowFlag(Qt::Window,true);//以窗体的形式
    pCarStatus->setWindowOpacity(1.2); //设置窗体的透明度。
    pCarStatus->show();
}

void QFormFunction::on_btn_sendCan_clicked()
{
    uint id  =  ui->line_ID->text().toUInt();
    QString text = ui->line_Data->text();

//    QByteArray arr = ui->line_Data->text().toLocal8Bit();

    uchar array[9] ={"\0"};
    bool ok = true;
    int length = text.size()/3 +1;

    for(int i = 0; i<length; i++)
    {
        if(ok)
        {
             array[i] =  (uchar) text.mid(i*3,2).toUInt(&ok,16);
        }
        else {

          QMessageBox::critical(this,"数据错误","请写入16进制的数据");
          return;
        }
    }

    bridge->threadCar.TransmitCANThread(id,array);
    int curRow = ui->tableinfo->rowCount(); //获取当前界面数据的条数
    ui->tableinfo->insertRow(curRow);
    this->createItemsARow(curRow, "send", " ", "1" ,ui->line_ID->text(),"数据帧","标准帧","8",text);

}
